using OracleInternal.Json.Common;

namespace OracleInternal.Json.Binary
{
	internal class StreamContext
	{
		internal int m_depth;

		internal BitSet m_stack;

		private BitSet m_hasChildren;

		internal bool m_pendingKey;

		internal bool m_done;

		internal IExceptionFactory m_exceptionFactory;

		internal StreamContext(IExceptionFactory exceptionFactory)
		{
			m_stack = new BitSet();
			m_hasChildren = new BitSet();
			m_exceptionFactory = exceptionFactory;
			Init();
		}

		internal void Init()
		{
			m_stack.Clear();
			m_hasChildren.Clear();
			m_depth = 0;
			m_pendingKey = false;
			m_done = false;
		}

		internal void StartObject()
		{
			BeginValue();
			m_depth++;
			m_stack.Set(m_depth);
			m_hasChildren.Clear(m_depth);
		}

		internal void PendingKey()
		{
			if (!InObject() || m_pendingKey)
			{
				throw OracleJsonExceptions.BAD_KEY.Create(m_exceptionFactory);
			}
			m_pendingKey = true;
		}

		internal void StartArray()
		{
			BeginValue();
			m_depth++;
			m_stack.Clear(m_depth);
			m_hasChildren.Clear(m_depth);
		}

		internal void End()
		{
			if (m_pendingKey)
			{
				throw OracleJsonExceptions.EXPECTED_VALUE.Create(m_exceptionFactory);
			}
			if (m_depth == 0)
			{
				throw OracleJsonExceptions.BAD_END.Create(m_exceptionFactory);
			}
			m_depth--;
			if (m_depth == 0)
			{
				m_done = true;
			}
		}

		internal void Primitive()
		{
			BeginValue();
			if (m_depth == 0)
			{
				m_done = true;
			}
		}

		private void BeginValue()
		{
			if (InObject() && !m_pendingKey)
			{
				throw OracleJsonExceptions.MISSING_KEY.Create(m_exceptionFactory);
			}
			if (m_done)
			{
				throw OracleJsonExceptions.EXTRA_EVENTS.Create(m_exceptionFactory);
			}
			m_pendingKey = false;
			m_hasChildren.Set(m_depth);
		}

		internal bool InObject()
		{
			if (m_depth > 0)
			{
				return m_stack.Get(m_depth);
			}
			return false;
		}

		internal bool HasChildren()
		{
			return m_hasChildren.Get(m_depth);
		}

		internal void Close()
		{
			if (!m_done)
			{
				throw OracleJsonExceptions.GENERATION_INCOMPLETE.Create(m_exceptionFactory);
			}
		}

		internal void SetExceptionFactory(IExceptionFactory f)
		{
			m_exceptionFactory = f;
		}
	}
}
